package cn.cqie.frame.service.impl;

import cn.cqie.frame.bo.add.AddDeptBo;
import cn.cqie.frame.entity.Dept;
import cn.cqie.frame.mapper.DeptMapper;
import cn.cqie.frame.service.DeptService;
import cn.cqie.frame.utils.AssertUtil;
import cn.cqie.frame.utils.BeanCopyUtils;
import cn.cqie.frame.vo.DeptVo;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author XYHL
 * @since 2021-10-09
 */
@Service
public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements DeptService {
    @Autowired
    private DeptService deptService;
    @Autowired
    private DeptMapper deptMapper;

    /**
     * 新增or更新部门信息
     * @param bo
     * @return
     */
    @Override
    public DeptVo saveOrUpdateDept(AddDeptBo bo) {
        LocalDateTime sysTime = LocalDateTime.now();
        Dept dept = BeanCopyUtils.copyObject(bo,Dept.class);
        dept.setCreateTime(sysTime);
        dept.setUpdateTime(sysTime);
        boolean insert = deptService.saveOrUpdate(dept);
        AssertUtil.isTrue(insert, "插入/更新菜单失败");
        return BeanUtil.toBean(dept,DeptVo.class);
    }

    /**
     * 查询部门信息
     * @return
     */
    @Override
    public List<DeptVo> queryDept() {
        // 查询菜单数据
        List<DeptVo> ret = new ArrayList<>();
        List<Dept> all = deptService.list();
        List<Dept> first = all.stream().filter(x -> x.getParentId() == null).sorted(Comparator.comparing(Dept::getSortCode)).collect(Collectors.toList());
        for (Dept mo : first) {
            ret.add(convertMoToVo(mo,all));
        }
        return  ret;
    }

    /**
     * 查询除id外的部门信息
     * @param id
     * @return
     */
    @Override
    public List<DeptVo> listParentList(Long id) {
        List<DeptVo> ret = new ArrayList<>();
        List<Dept> all = deptService.list();
        List<Long> excludeIdList=new ArrayList<>();
        if (id != null){
            //排除自己及全部后代
            addSelfAndChildren(id,excludeIdList,all);
            all=all.stream().filter(x->excludeIdList.contains(x.getId())==false).collect(Collectors.toList());
        }
        List<Dept> first=all.stream()
                .filter(x->x.getParentId()==null)
                .sorted(Comparator.comparing(Dept::getSortCode))
                .collect(Collectors.toList());
        for (Dept mo : first){
            ret.add(convertMoToVo(mo,all));
        }
        return ret;
    }

    /**
     * 删除部门信息
     * @param deptId
     * @return
     */
    @Override
    public Boolean deleteDept(Integer deptId) {
        boolean b = deptService.removeById(deptId);
        return b;
    }

    /**
     * 添加自己的子部门
     * @param id
     * @param idList
     * @param all
     */
    private void addSelfAndChildren(Long id, List<Long> idList, List<Dept> all) {
        //添加自己的id
        idList.add(id);
        //查找子女
        List<Dept> children = all.stream().filter(x->x.getParentId()!=null&& x.getParentId().equals(id))
                .collect(Collectors.toList());
        //递归添加子女id
        for (Dept child : children) {
            addSelfAndChildren(child.getId(), idList, all);
        }
    }

    /**
     * 确定上级部门名称
     * @param mo
     * @param all
     * @return
     */
    private DeptVo convertMoToVo(Dept mo, List<Dept> all) {
        DeptVo vo=new DeptVo();
        BeanUtils.copyProperties(mo,vo);
        //确定上级部门名称
        if (mo.getParentId()!=null){
            Dept parentDept=all.stream().filter(x->x.getId().equals(mo.getParentId())).findFirst().orElse(null);
            if (parentDept!=null){
                vo.setParentName(parentDept.getName());
            }
        }
        //子女
        List<Dept> moChildren =all.stream()
                .filter(x->x.getParentId()!=null&&x.getParentId().equals(mo.getId()))
                .sorted(Comparator.comparing(Dept::getSortCode))
                .collect(Collectors.toList());
        List<DeptVo> voChildren = new ArrayList<>();
        for (Dept child : moChildren) {
            voChildren.add(convertMoToVo(child,all));
        }
        vo.setChildren(voChildren);
        return vo;
    }

}
